Scrapbox to Markdown コードブロック
コードブロック
全然動かんw
コードの始めも終わりも動いてない
始めはそもそも実装入ってない
終わりは実装入れてるけど「今週前半の俺、これ何がしたいん?」状態
step2で終端を入れて、step3で各行(つまりcode:xxx to ```xxx)をする
step2で終端入れる
★1
リストやテーブルの場合、add \n で良い
コードブロックの場合、add ```
リストorテーブルかコードブロックかを判別する手段がない
state userにフラグがもう一つ要るなぁ
is_left_just_now() が「たった今ブロックから抜けました」を調べるやつ
ここに「たった今 "コード" ブロックから抜けました」も追加すればいい
フラグ更新戦略
if in block
更新しない
if not in block
code blockに入ったら更新する
code blockから出たら更新する
それ以外は更新しない
code blockに入ってるかどうかはstateが持っている
おお、すげえsta.icon
https://gyazo.com/36d393ef6185474108c353a8eaceebb0
ひょいと実装したらredだったテストコードが一気にgreen ok、入った
https://gyazo.com/ee5424bccb112c9f221946fe1603e968
step3で開始入れる
ok
まだ遠いのー
https://gyazo.com/5108dee76183e5707c91efb510ffaf39
1 なんか空行が空いちまうし中身もリストとして処理されてしまっている件
2 空行が入らないこっちは★1のextra insersionを```\nにすればok
なんで?
ここか
https://gyazo.com/dc14940df063dd689889c1935a11126f
is in listであっても、in code blockのときは変換しちゃいけない
あれ?is in blockとis in listの関係ってどうだっけ?
is in block
codeのときもtableのときも両方当てはまる
is in list
インデントの数で決めてる
0より大きければis in list=true
code:py
def _update_case_of_not_in_block(self, line, cur_indentdepth):
……
raise RuntimeError('Invalid start of block.') # ★これ入れてみたら普通に入りやがった
いや、入るか
blockじゃないときに専用記法があったらcodeblockやtableblockにするぞって話なだけで
おかしいな
codeblock中の行が全部 is not in blockと判定されている
なんで
テストコードではちゃんと動いてるんですけど
i==15とかi=17とか
コードブロック開始後に(なぜか入ってる)空行のせいでモードが戻されてる?
https://gyazo.com/0e99cdd4150da5e381b6c6c9f187b5ff
bingo
step2の中間生成物見てみたらこうなってた
https://gyazo.com/d9111daab1e67561d35c4b7b4b0039a9
step1では無事
https://gyazo.com/dcc00c27310b7738c7c1a7abda41b260
つまりjudge_extra_insertion()の問題
table:patterns
curlineのインデント数 prevlineのインデント数 どう解釈すべき? 備考
……
1 0 add \n リスト or ブロックがはじまた
始まりの前に空行入れてるけど
コードブロックの場合は入れちゃいけないんだ
done
あと少し
https://gyazo.com/20aab3fafec33e0c73bbfa9ff99d979c
要するに「本来nインデントであるはずの行」からインデントを外す処理をどこでやるか
step1とstep2は違うから、step3かそのメタしかない
step3はutilなのでlineしか受け付けないはず(自分がコードブロックの中にいるとかどうとかは関知しない)
よってメタで処理するしかない
あ、でもstep3ではinblockstate使ってメタな処理してるw
train.icon設計軽いとこういうほころびがでてくるよねー。。。
ほころびがでないような設計するってのは中々に難しい
中学からのプログラミング経験で言えば、ここは才能が絡む部分だと思う
世の中には変数名をa,a1,x,x1みたいにつけるプログラマーもいる(って話聞いたことある)
何らかの才能で芸術的にシンプルでほころびのない設計をやってしまうタイプ
俺は凡人なので愚直に対応していくしかない
せめてテストコードでホワイトボックス的に品質担保するくらいよ
code:py
# コードブロックの中身
if is_in_block and state.is_in_code_block():
# ただし code:xxx の開始行も in code block 判定なので
# 置換処理もここでやるしかない.
#
# パフォーマンスがダメそうなら, 開始行を in code block 判定にしない等の追加処理が必要か.
newline = re.sub(RE_CODE_BLOCK_START, '`\\2', newline)
#
# ★ここでインデントを解除する処理を書く
return newline
あああああ、これ厄介だな
機械的にインデント殺しちゃダメ
コードブロックの始まりが持つインデント数nを使って、nだけ除外してやらねばならない
code:scb
たとえば
list1
list2
code:py
for _ in range(4):
print('4回繰り返すじぇー')
コード終わり
これを変換するとこうなる
code:markdown
たとえば
- list1
- list2
`python
for _ in range(4):
print('4回繰り返すじぇー') # ここのインデントまで殺しちゃいけない
`
- ...★このダミーリスト部分はまだ実装できてないが。。。
- コード終わり
正規表現だとどうなる?
cur_indentdepth回のスペースをキャプチャして殺したいんですけど
r'( ){3}' これで3回
ここにcur_indentdepthを差し込む
r'( ){{}}'.format(cur_indentdepth)?
でもformat使うと{}自体が特別な意味もっちゃって、正規表現のn回指定が使えない
……愚直に文字列処理するか
ああ、待って、だめ
cur_indentdepthじゃなくて、コードブロック開始時のインデント深さが必要
this_codeblock_indentdepthみたいなの
indentdepth_of_startプロパティある
done
あと少し(意外と長い)
言語名の統一と
https://gyazo.com/64ebb1c07d3669412b29bc6ca07665d7
ahkのHotStringのとき(たぶん:ついててコードブロック判定になってしまってる)の謎のインデント https://gyazo.com/f5fe7d508f8fcce1512f9ed6acd750e3
言語名統一
newline = re.sub(RE_CODE_BLOCK_START, '```\\2', newline)
これの延長線やな
```でsplitして1番目の要素取り出して、あとは愚直に条件分岐するしかないか
パターン
js
javascript
JavaScriptやJSなど大文字小文字
hoge.jsなど拡張子
全部対応するのは明らかにしんどいので、どっかから流用するべき
markdown、というよりGFMがどうしているかも見るべき 拡張子をそのまま書いて処理はできるので、少なくとも xxxx.ext は ext をそのまま使えばいい
あとは言語名だけ書かれてるパターン
いくつか例出してみるか
js
code:ここの仕様 以前どこかで見た気がする
なにかのライブラリ使ってるんだよな、たしか
と思ったけど、よく考えたらGitHub側も多分同じようなの使ってるよな
つまり、scrapboxが対応している言語名指定の語彙≒GitHubの語彙とみなせるのでは?
そやな
自力実装なんてしたくないし、そうしよう
まとめ
code:xxxは```xxxにする
code:xxx.extは```extにする
正規表現だけでは無理くない?
できた!
ahkのHotStringのとき(たぶん:ついててコードブロック判定になってしまってる?)の謎のインデント あああああああああああああわかった
json parserでnormalize scbしてるせいだ
が、これだとコードブロック内のタブインデントも全部スペースになってしまう
どうすっかな
案は2つ
スペースのままで通す
僕はスペース派なので!
が、これだとタブ派の人達が使えなくなっちゃうね。。。
json parse時、コードブロックについてはnormalizeしない
というかscrapboxで通常ほ本文もタブとスペースが混ざってるの、なんか理由がある気がしてきた
shokaiさん達のエンジニアがあえてタブとスペースを混在させるやりづらさを放置するとは思えない
何か理由があるんだ?
今はプロトで早く形にしたいので、スペースのまま押し通しますんsta.icon*2